package dataprocessing;

public class FHReval
{
	public FHReval(short[] fhr,int N, short badfhrval)
	{}
	public static short[] Baseline(short[] fhr,int N,short badfhrval )
	{
		short[] y = new short[fhr.length];
		int N1 = fhr.length/N;		// ?nem lapol??szakaszok sz?
		float[] B = new float[N1+1];
		float sum;
		float max=0;
		int Nok;
		int Ngood=0;
		int j;
		for (int i=0; i<N1; i++)
		{
			sum=0.0f; Nok = 0;
			for (j=i*N; j<(i+1)*N;j++) if (fhr[j]!=badfhrval) {sum+=(float) fhr[j]; Nok++;}
			if (Nok>0) {sum/=(float)(Nok); Ngood++;}
			B[i+1]=sum;
			if (sum>max) max=sum;
		}
			
		float[] BB = new float[Ngood+1];
		j=0;
		for (int i=1; i<B.length; i++) if (B[i]>0.0f) {j++; BB[j]=B[i];}
		BB[0]=max;
		// backward dummy pass
		for (int i=Ngood-1; i>0; i--) if (Math.abs(BB[i]-max)<=60) BB[0]=0.95f*BB[0]+0.05f*BB[i];
		// forward pass
		for (int i=1; i<Ngood; i++) if (Math.abs(BB[i]-max)<=60) BB[i]=0.95f*BB[i-1]+0.05f*BB[i];
		// backward pass
		for (int i=Ngood-2; i>0; i--) BB[i]=0.95f*BB[i+1]+0.05f*BB[i]; 
		max = MathFunctions.Max(BB);
		BB[0]=max;
			
		// backward dummy pass
		for (int i=Ngood-1; i>0; i--) if (Math.abs(BB[i]-max)<=20) BB[0]=0.95f*BB[0]+0.05f*BB[i];
		// forward pass
		for (int i=1; i<Ngood; i++) if (Math.abs(BB[i]-max)<=20) BB[i]=0.95f*BB[i-1]+0.05f*BB[i];
		// backward pass
		for (int i=Ngood-2; i>0; i--) BB[i]=0.95f*BB[i+1]+0.05f*BB[i]; 
		max = MathFunctions.Max(BB);
		BB[0]=max;
			
		// backward dummy pass
		for (int i=Ngood-1; i>0; i--) if (Math.abs(BB[i]-max)<=15) BB[0]=0.95f*BB[0]+0.05f*BB[i];
		// forward pass
		for (int i=1; i<Ngood; i++) if (Math.abs(BB[i]-max)<=15) BB[i]=0.95f*BB[i-1]+0.05f*BB[i];
		// backward pass
		for (int i=Ngood-2; i>0; i--) BB[i]=0.95f*BB[i+1]+0.05f*BB[i]; 
		max = MathFunctions.Max(BB);
		BB[0]=max;
			
		// backward dummy pass
		for (int i=Ngood-1; i>0; i--) if (Math.abs(BB[i]-max)<=10) BB[0]=0.95f*BB[0]+0.05f*BB[i];
		// forward pass
		for (int i=1; i<Ngood; i++) if (Math.abs(BB[i]-max)<=10) BB[i]=0.95f*BB[i-1]+0.05f*BB[i];
		// backward pass
		for (int i=Ngood-2; i>0; i--) BB[i]=0.95f*BB[i+1]+0.05f*BB[i]; 
		max = MathFunctions.Max(BB);
		BB[0]=max;
			
		// backward dummy pass
		for (int i=Ngood-1; i>0; i--) if (Math.abs(BB[i]-max)<=5) BB[0]=0.95f*BB[0]+0.05f*BB[i];
		// forward pass
		for (int i=1; i<Ngood; i++) if (Math.abs(BB[i]-max)<=5) BB[i]=0.95f*BB[i-1]+0.05f*BB[i];
		// backward pass
		for (int i=Ngood-2; i>0; i--) BB[i]=0.95f*BB[i+1]+0.05f*BB[i]; 

		j=0;
		for (int i=1; i<B.length; i++) if (B[i]>0.0f) {j++; B[i]=BB[j];}


		for (int i=0; i<N1; i++)
			for( j=i*N; j<(i+1)*N; j++) y[j]=(short) Math.round(B[i+1]);
		for (int i=0; i<y.length;i++) if (fhr[i]==badfhrval) y[i]=badfhrval;
		return y;
	}

	public static short AvrBaseline(short[] fhr,int N,short badfhrval)
	{
		short[] baseline=Baseline(fhr,2,badfhrval);
		int Ngood=0;
		int sum=0;
		for (int i=0; i<fhr.length; i++)
		{
			if (fhr[i]!=badfhrval) {sum+=baseline[i]; Ngood++;}
		}
		if (Ngood>0) return (short)((float)sum/(float)Ngood);
		else return -1;
	}
	public static short[] Acc(short[] fhr,int N,short badfhrval )
	{
		short[] baseline = Baseline(fhr,2,badfhrval);
		short[] tmp = new short[baseline.length];
		for (int i=0; i<tmp.length; i++) if (fhr[i]>baseline[i]+5 || fhr[i]==badfhrval) tmp[i]=1; else tmp[i]=0;
		int timer,n;
		short max;
		n=0;
		short[] acc = new short[tmp.length];
		for (int i=0; i<tmp.length; i++)
		{
			if (tmp[i]==1) 
			{
				timer=0;
				max=0;
				while (i+timer+1<tmp.length && tmp[i+timer]==1) {timer++; if ((fhr[i]!=badfhrval) && (fhr[i+timer]-baseline[i+timer]>max)) max=(short)(fhr[i+timer]-baseline[i+timer]);} 
				if (timer>9 && max>10) // duration>15 sec && peak>15 BPM above baseline
				{
					n++;
					for (int idx=i; idx<i+timer; idx++) acc[idx]=1;
				}
				i=i+timer+1;
			}
		}
		return acc;
	}
	public static short[] Dec(short[] fhr,int N,short badfhrval )
	{
		return null;
	}
	public static float[] OscillatioAmp(short[] fhr,int N,short badfhrval )
	{
		float[] minmaxavr = new float[3];
		float OscAmp=0.0f;
		int mins = fhr.length/50;
		int sumamp = 0;
		int maxamp=0;
		int minamp=5000;
//		if (mins*50<fhr.length) mins++;
		int Ngood=mins;
		for (int i=0; i<mins; i++)
		{
			short max=0;
			short min=5000;
			for (int k=i*50; k<(i+1)*50; k++) 
			{
				if (fhr[k]>max && fhr[k]!=badfhrval) max=fhr[k];
				if (fhr[k]<min && fhr[k]!=badfhrval) min=fhr[k];
			}
			int amp = max-min;
			
			if (amp>maxamp && amp>0) maxamp=amp;
			if (amp<minamp && amp>0) minamp=amp;
			if (amp<0) {amp=0;Ngood--;}
			sumamp += amp; 
		}
		if (mins>0) OscAmp = (float)sumamp/(float)Ngood;
		else OscAmp=-1.0f;
		minmaxavr[0]=(float)minamp;
		minmaxavr[1]=(float)maxamp;
		minmaxavr[2]=OscAmp;
		return minmaxavr;
	}
	public static float OscillatioFreq(short[] fhr,int N,short badfhrval )
	{
		int pospeaks=0;
		int Ngood=0;
		int plato=0;
		for (int i=1; i<N-1; i++)
			if ((fhr[i-1]!=badfhrval) && (fhr[i]!=badfhrval) && (fhr[i+1]!=badfhrval))
			{
				Ngood++;
				if ((fhr[i]>fhr[i-1]) && (fhr[i]>fhr[i+1])) pospeaks++;
				else 
				{
					if ((plato==1) && (fhr[i]>fhr[i+1])) {pospeaks++; plato=0;}
					if ((plato==0)&&(fhr[i]>fhr[i-1])&& (fhr[i]==fhr[i+1]))	plato=1;	
				}
			}
			else plato=0;
		if (N>0) return ((float) pospeaks/((float)Ngood/50.0f));
		else return (-1.0f);
	}
}
